import { IBaseInfoColumn, HoverType } from '@shared/interfaces/baseInfo'
import { TitleService } from '@delon/theme'
import { deepCopy } from '@delon/util'

import * as dayjs from 'dayjs'
import { PageService } from '@shared/services/page.service'
import { EColumnType } from '@shared/enums'
import { readableAddress } from 'app/utils/helpers'
import { I18NService } from '@core'

export abstract class DetailBaseClass<T> {

  /* 加载 flag */
  loading = true

  /* 索引号，每个 detail 页面都会拿这个索引号去后台拿detail信息 */
  id: string

  /* 拿到的 detail 信息 */
  detailData: T = {} as T

  /** detailData 的副本, 撤销编辑使用 */
  copiedDetailData: T

  /* 第一列信息 */
  firstColumns: IBaseInfoColumn[] = []

  /* 第二列信息 */
  secondColumns: IBaseInfoColumn[] = []

  /* 底部列信息 */
  bottomColumnsRows: Array<IBaseInfoColumn[]> = []

  constructor(
    public pageService: PageService,
  ) { }

  triggerBaseEdit(): void {
    this.pageService.triggerBaseEdit(true)
  }

  cancelBase(): void {
    this.pageService.triggerBaseEdit(false)
  }

  saveBase(): void {
    this.pageService.triggerBaseEdit(false)
  }

  /* 初始化列信息，主要做一个事：将后台传回的 detail 信息写入到 columns 信息中，然后传给子组件去显示 */
  public initColumns() {
    if (this.firstColumns) this.initValue.call(this, this.firstColumns)
    if (this.secondColumns) this.initValue.call(this, this.secondColumns)
    this.bottomColumnsRows.forEach(columns => this.initValue.call(this, columns))
  }

  public checkDiff(index: string): boolean {
    return false
  }


  public initValue(columns: IBaseInfoColumn[]): void {
    columns.forEach(column => {
      const index = column.index as string
      if (!index) return
      if (this.checkDiff(index)) {
        column.diff = true
      }
      const type = column.type as string
      const keys = index.split('.')
      let value: any = this.detailData
      keys.forEach((key, idx, arr) => {
        value = value[key]

        // 如果当前 column 的索引为多层索引（foo.bar），那么需要处理 obj['foo'] 为 undefined 的异常
        if (arr.length > 1 && idx < arr.length - 1 && value === undefined) {
          value = {}
        }

        // 调用者传入自定义的处理方法：pipe，调用pipe方法对value进行处理, 默认取最后一个 key 来做处理
        if (column.pipe && idx === keys.length - 1) {
          value = column.pipe.call(this, value)
        }
      })
      // Checking the date type here to format the value
      if (type === EColumnType.Date) {
        /** 展示值不会覆盖 value */
        column.displayValue = dayjs(value).isValid() ? dayjs(value).format('YYYY-MM-DD HH:mm:ss') : '-'
      } else if (type === EColumnType.Address) {
        value = readableAddress(value)
      }
      column.value = (!!value && typeof value === 'string') ? value.trim() : value
    })
  }

  /* 在上传之前，需要把所有子组件修改后的内容转为后台能接受的格式 也就是 detailData: T */
  public updateColumns(): void {
    const update = function(arr: IBaseInfoColumn[]) {
      arr.forEach(column => {
        /* 如果是传模版进去，则不做赋值操作，会覆盖 */
        if (column.template) return
        const index = column.index as string
        const keys = index.split('.')
        let value = this.detailData
        keys.forEach((key, i) => {
          if (i === keys.length - 1) {
            return
          }
          value = value[key]
        })
        value[keys[keys.length - 1]] = column.value
      })
    }

    update.call(this, this.firstColumns)
    update.call(this, this.secondColumns)
    this.bottomColumnsRows.forEach(columns => update.call(this, columns))
  }

  clearColumnsErrorTips() {
    this.firstColumns.forEach((item: IBaseInfoColumn) => {
      if (item.validator) {
        item.validator.currentErrorTip = ''
        item.validator.isError = false
      }
      if (!item.disEditable) {
        item.hover = HoverType.Normal
      }
    })
    this.secondColumns.forEach((item: IBaseInfoColumn) => {
      if (item.validator) {
        item.validator.currentErrorTip = ''
        item.validator.isError = false
      }
      if (!item.disEditable) {
        item.hover = HoverType.Normal
      }
    })
    this.bottomColumnsRows.forEach((items: IBaseInfoColumn[]) => {
      items.forEach((item: IBaseInfoColumn) => {
        if (item.validator) {
          item.validator.currentErrorTip = ''
          item.validator.isError = false
        }
        if (!item.disEditable) {
          item.hover = HoverType.Normal
        }
      })
    })
  }

  checkEditValidation(): boolean {
    for (const item of this.firstColumns) {
      if (item.validator && item.validator.isError) {
        return false
      }
    }

    for (const item of this.secondColumns) {
      if (item.validator && item.validator.isError) {
        return false
      }
    }


    for (const items of this.bottomColumnsRows) {
      for (const item of items) {
        if (item.validator && item.validator.isError) {
          return false
        }
      }

    }

    return true
  }

  copyDetailData(srcData: T): T {
    return deepCopy(srcData)
  }


}
